package xin.nick.common.core.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.beans.BeanCopier;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Bean对象复制工具
 *
 * @author Nick
 * @since 2023/9/7
 */
@Slf4j
public class BeanCopierUtil {

    private BeanCopierUtil () {}

    /**
     * Bean复制对象缓存Map
     */
    private static final Map<String, BeanCopier> BEAN_COPIER_CACHE_MAP = new ConcurrentHashMap<>();


    /**
     * 复制属性信息
     *
     * @param source <S>
     * @param target <T>
     */
    public static <S, T> void copyProperties(S source, T target) {

        if (Objects.isNull(source)) {
            return;
        }
        if (Objects.isNull(target)) {
            return;
        }

        String key = source.getClass().getName() + "=to=" + target.getClass().getName();

        BeanCopier copier = BEAN_COPIER_CACHE_MAP.computeIfAbsent(key,
                theKey -> BeanCopier.create(source.getClass(), target.getClass(), false));

        copier.copy(source, target, null);
    }


    /**
     * 复制属性
     *
     * @param source      <S>
     * @param targetClass <T>
     * @return T
     */
    public static <S, T> T copyProperties(S source, Class<T> targetClass) {

        T target = null;
        try {
            target = targetClass.newInstance();
            copyProperties(source, target);
        } catch (InstantiationException | IllegalAccessException e) {
            log.error("Cannot copy properties", e);
        }

        return target;
    }


    /**
     * 拷贝List
     *
     * @param sourceList  List<S>
     * @param targetClass Class<T>
     * @return T
     */
    public static <S, T> List<T> copyToList(List<S> sourceList, Class<T> targetClass) {
        List<T> targetList = new ArrayList<>();
        for (S source : sourceList) {
            T target = copyProperties(source, targetClass);
            targetList.add(target);
        }
        return targetList;
    }

}
